package com.leisurexi.gedis.client.handler;

import com.leisurexi.gedis.client.util.RemotingUtils;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import lombok.extern.slf4j.Slf4j;

import java.net.SocketAddress;

/**
 * Log the channel status event.
 *
 * @author: leisurexi
 * @date: 2020-09-10 9:51
 */
@ChannelHandler.Sharable
@Slf4j
public class ConnectionEventHandler extends ChannelDuplexHandler {

    public static final ConnectionEventHandler INSTANCE = new ConnectionEventHandler();

    private ConnectionEventHandler() {
    }

    @Override
    public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) throws Exception {
        final String local = localAddress == null ? null : RemotingUtils.parseSocketAddressToString(localAddress);
        final String remote = remoteAddress == null ? "UNKNOWN" : RemotingUtils.parseSocketAddressToString(remoteAddress);
        if (local == null) {
            log.info("Try connect to {}", remote);
        } else {
            log.info("Try connect from {} to {}", local, remote);
        }
        super.connect(ctx, remoteAddress, localAddress, promise);
    }

    @Override
    public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
        log.debug("Connection disconnect to {}", RemotingUtils.parseRemoteAddress(ctx.channel()));
        super.disconnect(ctx, promise);
    }

    @Override
    public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
        log.debug("Connection closed: {}", RemotingUtils.parseRemoteAddress(ctx.channel()));
        super.close(ctx, promise);
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        log.debug("Connection channel registered: {}", RemotingUtils.parseRemoteAddress(ctx.channel()));
        super.channelRegistered(ctx);
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        log.debug("Connection channel unregistered: {}", RemotingUtils.parseRemoteAddress(ctx.channel()));
        super.channelUnregistered(ctx);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.debug("Connection channel active: {}", RemotingUtils.parseRemoteAddress(ctx.channel()));
        super.channelActive(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        String remoteAddress = RemotingUtils.parseRemoteAddress(ctx.channel());
        log.warn("Connection channel inactive: {}", remoteAddress);
        super.channelInactive(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        final String remoteAddress = RemotingUtils.parseRemoteAddress(ctx.channel());
        final String localAddress = RemotingUtils.parseLocalAddress(ctx.channel());
        log.warn("ExceptionCaught in connection: local[{}], remote[{}], close the connection! Cause[{}:{}]",
                localAddress, remoteAddress, cause.getClass().getSimpleName(), cause.getMessage());
        ctx.channel().close();
    }

}
